package normal

import (
	"encoding/json"
	"fmt"

	"gitee.com/micro-plat/fas/modules/sp"
	"gitee.com/micro-plat/fas/modules/util"

	"gitee.com/micro-plat/fas/modules/const/conf"
	"gitee.com/micro-plat/fas/modules/const/sql"
	"github.com/asaskevich/govalidator"
	"github.com/micro-plat/hydra"
	"github.com/micro-plat/lib4go/types"
)

type IBilling interface {
	GetDownChannelList(sourceSystemID int) (result string, err error)
	GetUpChannelList(sourceSystemID int) (result string, err error)
	DownChannelPay(param *DownPay) (info types.XMap, err error)
	DownChannelRefund(param *DownRefund) (info types.XMap, err error)
	UpChannelPay(param *UpPay) (info types.XMap, err error)
	UpChannelRefund(param *UpRefund) (info types.XMap, err error)
}

type Billing struct {
}

//NewBilling 获取对象
func NewBilling() (IBilling, error) {
	return &Billing{}, nil
}

//GetDownChannelList 获取下游渠道列表
func (b *Billing) GetDownChannelList(sourceSystemID int) (result string, err error) {
	//1. 验证参数
	c, err := hydra.C.DB().GetDB(conf.DBName)
	if err != nil {
		return "", err
	}
	//2.查询
	data, err := c.Query(sql.QueryFdDownChannelInfo, types.XMap{
		"source_system_id": sourceSystemID,
	})
	if err != nil {
		return "", fmt.Errorf("GetDownChannelList查询出错：%+v", err)
	}

	//3. 执行
	r, err := json.Marshal(map[string]interface{}{
		"result":           data,
		"source_system_id": sourceSystemID,
	})
	return string(r), err
}

//DownChannelPay 下游渠道扣款
func (b *Billing) DownChannelPay(param *DownPay) (info types.XMap, err error) {
	//1. 验证参数
	if b, err := govalidator.ValidateStruct(param); !b {
		return nil, fmt.Errorf("InnerDownChannelPay:参数验证错误err:%+v,param:%+v", err, param)
	}

	//2. 参数转换
	data, err := types.Struct2Map(param)
	if err != nil {
		return nil, fmt.Errorf("参数转换异常,err:%v", err)
	}
	requestParam, err := util.FloatDecimal(data)
	if err != nil {
		return nil, fmt.Errorf("参数精度转换异常,err:%v", err)
	}

	//3.执行
	result, msg, err := sp.ExecuteSP(sql.FDDownOrderFeePay, requestParam)
	if err != nil {
		return nil, fmt.Errorf("FDDownOrderFeePay调用存储过程失败:%+v", err)
	}
	return map[string]interface{}{
		"result": result,
		"msg":    msg,
	}, nil
}

//DownChannelRefund 下游渠道退款
func (b *Billing) DownChannelRefund(param *DownRefund) (info types.XMap, err error) {
	//1. 验证参数
	if b, err := govalidator.ValidateStruct(param); !b {
		return nil, fmt.Errorf("InnerDownChannelRefund:参数验证错误err:%+v,param:%+v", err, param)
	}

	//2. 参数转换
	data, err := types.Struct2Map(param)
	if err != nil {
		return nil, fmt.Errorf("参数转换异常,err:%v", err)
	}
	requestParam, err := util.FloatDecimal(data)
	if err != nil {
		return nil, fmt.Errorf("参数精度转换异常,err:%v", err)
	}

	//3. 执行
	result, err := sp.ExecuteSPWithResult(sql.FDDownOrderFeeRefund, requestParam)
	if err != nil {
		return nil, fmt.Errorf("FDDownOrderFeeRefund调用存储过程失败:%+v", err)
	}

	return map[string]interface{}{
		"result": result,
	}, nil
}

//GetUpChannelList 获取上游渠道
func (b *Billing) GetUpChannelList(sourceSystemID int) (result string, err error) {

	db, err := hydra.C.DB().GetDB(conf.DBName)
	if err != nil {
		return "", err
	}

	data, err := db.Query(sql.QueryFdUpChannelInfo, types.XMap{
		"source_system_id": sourceSystemID,
	})
	if err != nil {
		return "", fmt.Errorf("FDUpChannelInfo查询出错:%v", err)
	}

	r, err := json.Marshal(map[string]interface{}{
		"result": data,
	})
	return string(r), err
}

//UpChannelPay 上游渠道扣款
func (b *Billing) UpChannelPay(param *UpPay) (info types.XMap, err error) {
	//1. 验证参数
	if b, err := govalidator.ValidateStruct(param); !b {
		return nil, fmt.Errorf("InnerUpChannelPay:参数验证错误err:%+v,param:%+v", err, param)
	}

	//2. 参数转换
	data, err := types.Struct2Map(param)
	if err != nil {
		return nil, fmt.Errorf("参数转换异常,err:%v", err)
	}
	requestParam, err := util.FloatDecimal(data)
	if err != nil {
		return nil, fmt.Errorf("参数精度转换异常,err:%v", err)
	}

	//3. 执行
	result, err := sp.ExecuteSPWithResult(sql.FDUpOrderFeePay, requestParam)
	if err != nil {
		return nil, fmt.Errorf("FDUpOrderFeePay 调用存储过程失败:%+v", err)
	}

	return map[string]interface{}{
		"result":         result,
		"trade_order_no": data["trade_order_no"],
	}, nil
}

//UpChannelRefund 上游渠道退款
func (b *Billing) UpChannelRefund(param *UpRefund) (info types.XMap, err error) {
	//1. 验证参数
	if b, err := govalidator.ValidateStruct(param); !b {
		return nil, fmt.Errorf("InnerUpChannelRefund:参数验证错误err:%+v,param:%+v", err, param)
	}

	//2. 参数转换
	data, err := types.Struct2Map(param)
	if err != nil {
		return nil, fmt.Errorf("参数转换异常,err:%v", err)
	}
	requestParam, err := util.FloatDecimal(data)
	if err != nil {
		return nil, fmt.Errorf("参数精度转换异常,err:%v", err)
	}

	//3. 执行
	result, err := sp.ExecuteSPWithResult(sql.FDUpOrderFeeRefund, requestParam)
	if err != nil {
		return nil, fmt.Errorf("FDUpOrderFeeRefund调用存储过程失败:%+v", err)
	}

	return map[string]interface{}{
		"result":          result,
		"trade_order_no":  data["trade_order_no"],
		"trade_refund_no": data["trade_refund_no"],
	}, nil
}
